{*******************************************************************************
 *                                                                             *
 *          Mathengine                                                         *
 *                                                                             *
 *          (C)Copyright Jimx 2011                                             *
 *                                                                             *
 *          http://math-engine.googlecode.com                                  *
 *                                                                             *
 *******************************************************************************
 *  This file is part of Mathengine.                                           *
 *                                                                             *
 *  Mathengine is free software:                                               *
 *  you can redistribute it and/or modify                                      *
 *  it under the terms of the GNU General Public License as published by       *
 *  the Free Software Foundation, either version 3 of the License, or          *
 *  (at your option) any later version.                                        *
 *                                                                             *
 *  Mathengine is distributed                                                  *
 *  in the hope that it will be useful,                                        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
 *  GNU General Public License for more details.                               *
 *                                                                             *
 *  You should have received a copy of the GNU General Public License          *
 *  along with Mathengine.                                                     *
 *  If not, see <http://www.gnu.org/licenses/>.                                *
 *******************************************************************************}
unit sci.types;

interface
uses
  Classes;

{$LONGSTRINGS ON}
{$OPTIMIZATION ON}
{$STACKFRAMES OFF}
{$BOOLEVAL OFF}
{$WARN IMPLICIT_STRING_CAST OFF}
{$WARN IMPLICIT_STRING_CAST_LOSS OFF}

type
  TValueType = (TYPE_INT, TYPE_FLOAT, TYPE_BOOL, TYPE_STRING);

  TValue = Variant;
{$REGION 'TExpressionValue'}
 { TValueData = packed record
    case TValueType of
    TYPE_INT: (i: integer);
    TYPE_FLOAT: (r: real);
    TYPE_BOOL: (b: boolean);
    TYPE_STRING: (s: PString);
  end;

  TValue = record
    vd: TValueData;
    // TExpressionValue <=> Integer
    class operator Implicit(a: TValue): integer;
    class operator Implicit(a: integer): TValue;
    // TExpressionValue <=> Real
    class operator Implicit(a: TValue): real;
    class operator Implicit(a: real): TValue;
    class operator Negative(a: TValue): TValue;
    class operator Equal(a: TValue; b: integer): boolean;
    class operator NotEqual(a: TValue; b: integer): boolean;
    class operator GreaterThan(a: TValue; b: integer): boolean;
    class operator Inc(a: TValue): TValue;

    class operator Add(a, b: TValue): TValue;
    class operator Subtract(a, b: TValue): TValue;
    class operator Multiply(a, b: TValue): TValue;
    class operator Divide(a, b: TValue): TValue;
  end;     }
{$ENDREGION}

  TData = record
    input: PChar;
    output: TStringList;
  end;

procedure initData(var d: TData);

implementation

{$REGION 'TExpressionValue'}
{class operator TValue.Implicit(a: TValue): integer;
begin
  Result := a.vd.i;
end;

class operator TValue.Implicit(a: integer): TValue;
begin
  Result.vd.i := a;
  Result.vd.r := a;
end;

class operator TValue.Implicit(a: TValue): real;
begin
  Result := a.vd.r;
end;

class operator TValue.Implicit(a: real): TValue;
begin
  Result.vd.i := round(a);
  Result.vd.r := a;
end;

class operator TValue.Negative(a: TValue): TValue;
begin
  Result.vd.i := -a.vd.i;
  Result.vd.r := -a.vd.r;
  Result.vd.b := not a.vd.b;
end;

class operator TValue.Equal(a: TValue; b: Integer): boolean;
begin
  Result := a.vd.i = b;
end;

class operator TValue.NotEqual(a: TValue; b: Integer): boolean;
begin
  Result := a.vd.i <> b;
end;

class operator TValue.GreaterThan(a: TValue; b: integer): boolean;
begin
  Result := a.vd.i > b;
end;

class operator TValue.Inc(a: TValue): TValue;
begin
  Result.vd.i := a.vd.i + 1;
end;

class operator TValue.Add(a, b: TValue): TValue;
begin
  Result.vd.i := a.vd.i + b.vd.i;
  Result.vd.r := a.vd.r + b.vd.r;
end;

class operator TValue.Subtract(a, b: TValue): TValue;
begin
  Result.vd.i := a.vd.i - b.vd.i;
  Result.vd.r := a.vd.r - b.vd.r;
end;

class operator TValue.Multiply(a, b: TValue): TValue;
begin
  Result.vd.i := a.vd.i * b.vd.i;
  Result.vd.r := a.vd.r * b.vd.r;
end;

class operator TValue.Divide(a, b: TValue): TValue;
begin
  Result.vd.i := a.vd.i div b.vd.i;
  Result.vd.r := a.vd.r / b.vd.r;
end;            }
{$ENDREGION}

procedure initData(var d: TData);
begin
  d.output := TStringList.Create;
end;

end.
